﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Net.Http.Json;
using System.Threading;
using System.Threading.Tasks;

namespace ConsoleApp1
{
    class Program
    {
        private static string WorkFolder = @"E:\Argo\src\NugetTest\BlazorApp1\BlazorApp1";
        private static string PackageName = "bootstrapblazor";
        private static string NugetFolder = $"E:\\.nuget\\packages\\{PackageName}";
        private static int DefaultRestorePackageCount = 3;
        private static IEnumerable<string> ManualVersionList = new string[] { "5.4.0", "5.4.2", "5,4,3", "5.4.4", "5.4.5" };

        static async Task Main(string[] args)
        {
            using var cancelSourceToken = new CancellationTokenSource();

            Console.CancelKeyPress += async (sender, args) =>
            {
                Console.Write("Ctrl+C Exit ...");
                cancelSourceToken.Cancel();
                await Task.Delay(200);
            };

            // fetch versions 
            while (!cancelSourceToken.IsCancellationRequested)
            {
                //await AutoFetch(cancelSourceToken);
                await ManualFetch(cancelSourceToken);
            }
        }

        private static async Task ManualFetch(CancellationTokenSource cancelSourceToken)
        {
            try
            {
                foreach (var version in ManualVersionList)
                {
                    await RestoreBlazor(version, NugetFolder);
                }
                Console.ForegroundColor = ConsoleColor.Green;
                Console.WriteLine($"{DateTime.Now}: Waiting ...");
                Console.ForegroundColor = ConsoleColor.White;
                await Task.Delay(1000 * 30 * 5, cancelSourceToken.Token);
            }
            catch (Exception ex)
            {
                Console.ForegroundColor = ConsoleColor.Red;
                Console.WriteLine(ex.Message);
                Console.ForegroundColor = ConsoleColor.White;
                await Task.Delay(1000 * 60, cancelSourceToken.Token);
            }
        }

        private static async Task AutoFetch(CancellationTokenSource cancelSourceToken)
        {
            try
            {
                var url = $"https://api.nuget.org/v3/registration5-gz-semver2/{PackageName}/index.json";
                var client = new HttpClient(new HttpClientHandler
                {
                    AutomaticDecompression = DecompressionMethods.All
                });
                var packInfo = await client.GetFromJsonAsync<PackageInfo>(url, cancelSourceToken.Token);

                var counter = 1;
                var betaCounter = 1;
                for (var index = packInfo.Count - 1; index >= 0; index--)
                {
                    var item = packInfo.Items[index];
                    var packageVersions = await client.GetFromJsonAsync<PackageVersions>(item.Id, cancelSourceToken.Token);

                    for (var versionIndex = packageVersions.Items.Count - 1; versionIndex >= 0; versionIndex--)
                    {
                        var packItem = packageVersions.Items[versionIndex];
                        if (packItem.CatalogEntry.Listed)
                        {
                            var version = packItem.CatalogEntry.Version;
                            if (IsBetaVersion(version))
                            {
                                if (betaCounter > DefaultRestorePackageCount)
                                {
                                    continue;
                                }
                                betaCounter++;
                            }
                            else
                            {
                                if (counter > DefaultRestorePackageCount)
                                {
                                    continue;
                                }
                                counter++;
                            }

                            await RestoreBlazor(version, NugetFolder);

                            if (betaCounter > DefaultRestorePackageCount && counter > DefaultRestorePackageCount)
                            {
                                break;
                            }
                        }
                    }

                    if (betaCounter > DefaultRestorePackageCount && counter > DefaultRestorePackageCount)
                    {
                        break;
                    }
                }

                await Task.Delay(1000 * 60, cancelSourceToken.Token);
            }
            catch (Exception ex)
            {
                Console.ForegroundColor = ConsoleColor.Red;
                Console.WriteLine(ex.Message);
                Console.ForegroundColor = ConsoleColor.White;
                await Task.Delay(1000 * 30, cancelSourceToken.Token);
            }
        }

        private static async Task RestoreBlazor(string version, string nugetFolder)
        {
            Console.ForegroundColor = ConsoleColor.Cyan;
            Console.WriteLine($"{DateTime.Now}: Add Bootstrap Blazor ...  {version}");
            Console.ForegroundColor = ConsoleColor.White;
            RunCommand("dotnet.exe", $"add package BootstrapBlazor --version {version}");
            await Task.Delay(5000);

            ClearPackage(version, nugetFolder);
            await Task.Delay(5000);

            Console.ForegroundColor = ConsoleColor.Yellow;
            Console.WriteLine($"{DateTime.Now}: Restore Bootstrap Blazor ...  {version}");
            Console.ForegroundColor = ConsoleColor.White;
            RunCommand("dotnet.exe", $"restore --no-cache");
            await Task.Delay(5000);

            ClearPackage(version, nugetFolder);
            await Task.Delay(5000);
        }

        private static void ClearPackage(string version, string nugetFolder)
        {
            Console.ForegroundColor = ConsoleColor.Red;
            Console.WriteLine($"{DateTime.Now}: Clear Nuget ...");
            var folder = Path.Combine(nugetFolder, version);
            if (Directory.Exists(folder))
            {
                Directory.Delete(folder, true);
                Console.WriteLine($"{DateTime.Now}: Done.");
            }
            Console.ForegroundColor = ConsoleColor.White;
        }

        private static void RunCommand(string command, string args)
        {
            using var dotnetAddCmd = new Process();
            dotnetAddCmd.StartInfo = new ProcessStartInfo(command, args)
            {
                WorkingDirectory = WorkFolder
            };
            dotnetAddCmd.Start();
            dotnetAddCmd.WaitForExit();
        }

        private static bool IsBetaVersion(string version) => version.Contains("-Beta", StringComparison.OrdinalIgnoreCase);
    }
}
